package top.withwings.bonus.bonus.repo;

import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;
import top.withwings.bonus.bonus.pojo.bonus.rule.BonusRule;
import top.withwings.bonus.bonus.pojo.bonus.rule.BonusRuleTypeCaster;
import top.withwings.bonus.common.pojo.ReinforcedBeanPropertySqlParameterSource;

import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Repository
public class BonusRuleRepo {

    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Autowired
    private JdbcTemplate jdbcTemplate;


    public void delete(int bonusRuleId) {

        String sql = " delete from bonus_rule where id = ?";
        jdbcTemplate.update(sql, bonusRuleId);

    }

    public void update(BonusRule bonusRule) {

        String sql = " update "
                + " bonus_rule "
                + " set"
                + " name=:name,"
                + " description=:description,"
                + " param_map_json =:paramMapJson"
                + " where "
                + " id =:id";
        Map<String, Object> params = new HashMap<>();

        params.put("paramMapJson", JSON.toJSONString(bonusRule.getParamMap()));

        SqlParameterSource sqlParameterSource = new ReinforcedBeanPropertySqlParameterSource(bonusRule, params);

        namedParameterJdbcTemplate.update(sql, sqlParameterSource);

    }


    public int create(BonusRule bonusRule) {

        String sql = " insert into bonus_rule(type,name,description, param_map_json) values(" +
                " :type,:name,:description,:paramMapJson)";

        Map<String, Object> params = new HashMap<>();

        params.put("paramMapJson", JSON.toJSONString(bonusRule.getParamMap()));

        SqlParameterSource sqlParameterSource = new ReinforcedBeanPropertySqlParameterSource(bonusRule, params);

        KeyHolder keyHolder = new GeneratedKeyHolder();
        namedParameterJdbcTemplate.update(sql, sqlParameterSource, keyHolder);
        return keyHolder.getKey().intValue();

    }


    public List<BonusRule> listAll() {
        String sql = " select id, type, name ,description,param_map_json from bonus_rule";
        return namedParameterJdbcTemplate.query(sql, new BonusRuleMapper());
    }

    public BonusRule findById(Integer ruleId) {
        String sql = " select id, type, name ,description,param_map_json from bonus_rule where id = ?";
        return jdbcTemplate.queryForObject(sql, new BonusRuleMapper(), ruleId);

    }

    private static class BonusRuleMapper implements RowMapper<BonusRule> {


        @Override
        public BonusRule mapRow(ResultSet rs, int rowNum) throws SQLException {

            int id = rs.getInt("id");
            String type = rs.getString("type");
            String name = rs.getString("name");
            String description = rs.getString("description");
            LinkedHashMap<String, BigDecimal> decimalMap = JSON.parseObject(rs.getString("param_map_json"), LinkedHashMap.class);
            LinkedHashMap<String, Double> paramMap = convertToDouble(decimalMap);


            BonusRule rule = new BonusRule(id, name, paramMap);
            rule.setType(type);
            rule.setDescription(description);

            return BonusRuleTypeCaster.castToSubClass(rule);

        }

        private LinkedHashMap<String, Double> convertToDouble(LinkedHashMap<String, BigDecimal> decimalMap) {
            LinkedHashMap<String, Double> result = new LinkedHashMap<>();
            for (String s : decimalMap.keySet()) {
                result.put(s, decimalMap.get(s).doubleValue());
            }
            return result;
        }
    }

}
